#include <device.h>
#include <errno.h>
#include <clk.h>
#include <irq.h>
#include <init.h>
#include <console.h>
#include <readline.h>
#include <parse.h>
#include <stdio.h>
#include <machine.h>
#include <memory.h>
#include <arch/io.h>
#include <arch/cache.h>
#include <arch/cpu/soc/s3c2440.h>
#include <arch/cpu/soc/clk.h>
#include <arch/cpu/soc/irq.h>

extern uint32_t __vectors_start[], __vectors_end[];
void main(void);

void start_kernel(void)
{
	struct driver *devp;
	uint32_t *vecp_src, *vecp_dst;
	struct machine_desc *md;
	initcall_t *init_fn;
	exitcall_t *exit_fn;
	int ret;

	md = machine_lookup();
	if (IS_ERR(md)) 
		while (1);

	vecp_dst = (uint32_t *)0;
	for (vecp_src = __vectors_start; vecp_src < __vectors_end; vecp_src++) {
		*vecp_dst = *vecp_src;
		vecp_dst++;
	}
	
	for_each_earliest_initcall(init_fn) {
		ret = (*init_fn)();
		if (IS_ERR(ret)) 
			while (1);
	}

	ret = md->init_machine();
	if (IS_ERR(ret))
		while (1);

	ret = memory_init();
	if (IS_ERR(ret)) 
		while (1);

	for_each_early_initcall(init_fn) {
		ret = (*init_fn)();
		if (IS_ERR(ret)) 
			while (1);
	}

	local_irq_enable();

	for_each_core_initcall(init_fn) {
		ret = (*init_fn)();
		if (IS_ERR(ret))
			while (1);
	}

	for_each_driver(devp) {
		register_driver(devp);
	}

	for_each_late_initcall(init_fn) {
		ret = (*init_fn)();
		if (IS_ERR(ret))
			while (1);
	}

	main();

	for_each_exitcall(exit_fn) {
		(*exit_fn)();
	}
	
	while (1);
}

void main(void)
{
	while (1) {
		readline(CONFIG_SYS_PROMPT);
		run_command(console_buffer);
	}

	while (1);
}

/*
	// debug
	{
		struct s3c2440_gpio *gpio = s3c2440_get_base_gpio(); 
		uint32_t tmp;

		tmp  = readl(&gpio->gpfdat);
		tmp &= ~0x20;
		writel(tmp, &gpio->gpfdat);
	}
*/	

